package com.yanggu.jetcache.controller;

import com.alicp.jetcache.anno.*;
import com.yanggu.jetcache.entity.UserEntity;
import com.yanggu.jetcache.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import static com.alicp.jetcache.anno.CacheType.*;

@RestController
@RequestMapping("/users")
public class UserController {

    @Autowired
    private UserService userService;

    /**
     * 使用本地缓存，指定了过期时间和key生成逻辑
     * <p>condition。执行结果为true时，将方法返回值放入缓存中</p>
     */
    @GetMapping("/local/{id}")
    @Cached(name = "user:local:", key = "#id", expire = 10, cacheType = LOCAL, condition = "#id > 1")
    public UserEntity getUserById(@PathVariable Long id) {
        return userService.getById(id);
    }

    /**
     * 使用远程缓存，指定了过期时间和key生成逻辑
     * <p>postCondition。对方法返回值进行计算，执行结果为true时，将方法返回值放入缓存中</p>
     *
     */
    @GetMapping("/remote/{id}")
    @Cached(name = "user:remote:", key = "#id", expire = 20, cacheType = REMOTE, postCondition = "#result.id > 1")
    public UserEntity getUserById2(@PathVariable Long id) {
        return userService.getById(id);
    }

    /**
     * 使用二级缓存: 本地缓存和远程缓存，指定了过期时间和key生成逻辑
     */
    @GetMapping("/both/{id}")
    @Cached(name = "user:both:", key = "#id", localExpire = 10, expire = 20, cacheType = BOTH, syncLocal = true)
    public UserEntity getUserById3(@PathVariable Long id) {
        return userService.getById(id);
    }

    /**
     * 更新本地缓存数据
     */
    @PutMapping("/{id}")
    @CacheUpdate(name = "user:local:", key = "#user.id", value = "#user")
    public boolean updateUser(@PathVariable Long id, @RequestBody UserEntity user) {
        user.setId(id);
        return userService.updateById(user);
    }

    /**
     * 删除本地缓存
     * <p>CacheInvalidate注解支持删除多个缓存数据</p>
     */
    @DeleteMapping("/{id}")
    @CacheInvalidate(name = "user:local:", key = "#id")
    @CacheInvalidate(name = "user:remote:", key = "#id")
    public boolean deleteUser(@PathVariable Long id) {
        return userService.removeById(id);
    }

    /**
     * 使用多级缓存，指定了过期时间和key生成逻辑
     * <p>CacheRefresh刷新key对应的value</p>
     * <p>CachePenetrationProtect防止缓存击穿，获取数据时，手动加锁，只有一个线程进行访问</p>
     */
    @GetMapping("/both2/{id}")
    @CachePenetrationProtect(timeout = 10)
    @CacheRefresh(refresh = 15, stopRefreshAfterLastAccess = 100)
    @Cached(name = "user:both2:", key = "#id", localExpire = 10, expire = 20, cacheType = BOTH)
    public UserEntity getUserById4(@PathVariable Long id) {
        return userService.getById(id);
    }

}